﻿using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using Vbyte.DataSource.Cache;

namespace Vbyte.Configuration
{
    /// <summary>
    /// 数据交互属性配置
    /// </summary>
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
    public class DataExchangeAttribute : Attribute
    {
        /// <summary>
        /// 数据交互属性配置
        /// </summary>
        /// <param name="format">原始数据格式</param>
        /// <param name="bind">
        /// 远程数据URI绑定地址，支持外置参数构建绑定和属性名称或索引绑定。
        /// <para>外置参数配置格式：{实例类型::函数名['参数名']}</para>
        /// <para>名称或索引配置格式：{属性名称}或标志依据的{属性索引}</para>
        /// </param>
        /// <param name="id">标志依据，公用属性定义{属性名称}、系统属性定义$...$。</param>
        public DataExchangeAttribute(RawFormat format, string bind, string[] id)
        {
            DataFormat = format;
            URIBind = bind;
            IdentityDepend = id;
        }

        /// <summary>
        /// 原始数据格式
        /// </summary>
        public RawFormat DataFormat { get; set; }

        private const string ParamBindPattern = "\\{(?<TypeName>([\\w_\\-]+)(\\.([\\w_\\-]+))*)::(?<MethodName>[\\w_\\-]+)\\['(?<ParamName>[\\w_\\-]+)'\\]\\}";
        private bool blnParamBindedFlag = false;
        /// <summary>
        /// 绑定外置的URL参数配置
        /// </summary>
        private void BindParamConfig()
        {
            //Pattern: \{(?<TypeName>([\w_\-]+)(\.([\w_\-]+))*)::(?<MethodName>[\w_\-]+)\['(?<ParamName>[\w_\-]+)'\]\}
            //{BestTone.DataSource.Imp.FoodSearch::GetDetailRaw['url']}
            //{实例类型::函_数-名['参数名']}
            //-------Found MATCH---Length:7----
            //({实例类型::函_数-名['参数名']})(实例类型)()()(实例类型)(函_数-名)(参数名)
            ParamsBuild pBuildConfig = ParamsBuild.ConfigInstance;
            _urlBind = Regex.Replace(_urlBind, ParamBindPattern, m => ReplaceParamBind(m, pBuildConfig), RegexOptions.IgnoreCase);

            #region 绑定可交替的URI地址请求
            if (!string.IsNullOrEmpty(_urlAlternateBind))
            {
                _urlAlternateBind = Regex.Replace(_urlAlternateBind, ParamBindPattern, m => ReplaceParamBind(m, pBuildConfig), RegexOptions.IgnoreCase);
            }
            #endregion

            blnParamBindedFlag = true;
        }

        private string ReplaceParamBind(Match m, ParamsBuild bindConfig)
        {
            MethodParams mParams = bindConfig.GetParamConfig(m.Groups["TypeName"].Value, m.Groups["MethodName"].Value);
            if (mParams == null)
            {
                throw new System.Configuration.ConfigurationErrorsException(string.Format("没有找到类：{0}的方法：{1}的参数配置信息！",
                    m.Groups["TypeName"].Value,
                    m.Groups["MethodName"].Value));
            }
            Param p = mParams.GetParam(m.Groups["ParamName"].Value);
            if (p == null)
            {
                throw new System.Configuration.ConfigurationErrorsException(string.Format("没有找到类：{0}的方法：{1}的参数[{2}]的配置信息！",
                     m.Groups["TypeName"].Value,
                     m.Groups["MethodName"].Value,
                     m.Groups["ParamName"].Value)); 
            }
            return p.Value;
        }

        private string _urlBind;
        /// <summary>
        /// 远程数据URI绑定地址
        /// </summary>
        public string URIBind 
        {
            get 
            {
                if (!UseParamBind)
                {
                    return _urlBind;
                }
                else
                {
                    if (!blnParamBindedFlag) BindParamConfig();
                    return _urlBind;
                }
            }
            set { _urlBind = value; } 
        }

        private string _urlAlternateBind;
        /// <summary>
        /// 可替换的其他URI地址绑定
        /// </summary>
        public string AlternateURIBind
        {
            get
            {
                if (!UseParamBind)
                {
                    return _urlAlternateBind;
                }
                else
                {
                    if (!blnParamBindedFlag) BindParamConfig();
                    return _urlAlternateBind;
                }
            }
            set { _urlAlternateBind = value; }
        }

        /// <summary>
        /// 标志依据，公用属性定义{属性名称}、系统属性定义$...$。
        /// </summary>
        public string[] IdentityDepend { get; set; }

        /// <summary>
        /// 数据交互的协议规范定义：如HTTP头的Cookie,Referer,User-Agent信息。
        /// <para>(JSON序列化格式)</para>
        /// </summary>
        public string ExchangeHead { get; set; }

        private Type dateBindType = typeof(PropertyBindIdentity);
        /// <summary>
        /// 数据标志绑定类型，该类型可绑定动态获取的自定义变量值。
        /// </summary>
        public Type IdentityDindType
        {
            get { return dateBindType; }
            set { dateBindType = value; }
        }

        private bool blnUseParamBind = false;
        /// <summary>
        /// 是否使用外置参数配置绑定
        /// </summary>
        public bool UseParamBind
        {
            get { return blnUseParamBind; }
            set { blnUseParamBind = value; }
        }
    }

    /// <summary>
    /// 原始数据格式
    /// </summary>
    public enum RawFormat : byte
    { 
        /// <summary>
        /// JSON数据格式
        /// </summary>
        JSON = 0,

        /// <summary>
        /// XML数据格式
        /// </summary>
        XML = 1,

        /// <summary>
        /// 二进制数据
        /// </summary>
        Binnary = 2
    }
}
